home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / PlainText / PTConverts.c < prev    next >
Text File  |  1994-02-01  |  19KB  |  851 lines

  1. /*----------------------------- Includes ---------------------------------*/
  2.     
  3. #include "PlainText.h"
  4. #include "PTGlobs.h"
  5.  
  6. /*---------------------------- Declarations ------------------------------*/
  7.  
  8. void StraightToCurly(WindowPtr);
  9. void CurlyToStraight(WindowPtr);
  10. void AddLinefeeds(WindowPtr);
  11. void StripLinefeeds(WindowPtr);
  12. void LinefeedstoReturns(WindowPtr);
  13. void ReturnstoLinefeeds(WindowPtr);
  14. void WordWrap(WindowPtr,Boolean);
  15. void TabsToSpaces(WindowPtr);
  16. void SpacesToTabs(WindowPtr);
  17. void FormParagraphs(WindowPtr);
  18. void EnTabAndShift(WindowPtr,int);
  19.  
  20. Handle FillTempHandle(TE32KHandle tH,long selStart,long selEnd)
  21. {
  22.     Handle undoH;
  23.     
  24.     undoH=NewHandle(selEnd-selStart);
  25.     if (MemError() || StripAddress(undoH)==nil) {
  26.         doMessage(6);
  27.         undoH=0;
  28.     } else {
  29.         HLock(undoH);
  30.         HLock((**tH).hText);
  31.         BlockMove(*((**tH).hText) + selStart,*undoH,selEnd-selStart);
  32.         HUnlock(undoH);
  33.         HUnlock((**tH).hText);
  34.     }
  35.     return undoH;
  36. }
  37.  
  38. void StraightToCurly(WindowPtr wind)
  39. {
  40.     TE32KHandle tH;
  41.     long selStart,selEnd,i,dirty=0;
  42.     register char *p;
  43.     Rect box;
  44.     Handle undoH;
  45.     
  46.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  47.         selStart=(**tH).selStart;
  48.         selEnd=(**tH).selEnd;
  49.         if(selStart>=selEnd) {
  50.             selStart=0;
  51.             selEnd=(**tH).teLength;
  52.         }
  53.         
  54.         undoH=FillTempHandle(tH,selStart,selEnd);
  55.         
  56.         HLock((**tH).hText);
  57.         p=*(**tH).hText+selStart;
  58.         for(i=selStart;i<selEnd;i++,p++) {
  59.             if(*p=='\'') {
  60.                 if(!i || isspace(*(p-1)))
  61.                     *p='‘';
  62.                 else
  63.                     *p='’';
  64.                 dirty=1;
  65.             } else if(*p=='\"') {
  66.                 if(!i || isspace(*(p-1)))
  67.                     *p='“';
  68.                 else
  69.                     *p='”';
  70.                 dirty=1;
  71.             }
  72.         }
  73.         HUnlock((**tH).hText);
  74.         if(dirty) {
  75.             if((**tH).undoBuf)
  76.                 DisposeHandle((**tH).undoBuf);
  77.             (**tH).undoBuf=undoH;
  78.             (**tH).undoStart = selStart;
  79.             (**tH).undoEnd = selEnd;
  80.             (**tH).resetUndo = false;
  81.             (**tH).undoDelta = 0;
  82.             ((DocumentPeek)wind)->fNeedtoSave=true;
  83.             SetPort(wind);
  84.             GetContentRect(wind,&box);
  85.             InvalRect(&box);
  86.             EraseRect(&box);
  87.         } else if(undoH)
  88.             DisposeHandle(undoH);
  89.     }
  90. }
  91.  
  92. void CurlyToStraight(WindowPtr wind)
  93. {
  94.     TE32KHandle tH;
  95.     long selStart,selEnd,i,dirty=0;
  96.     register char *p;
  97.     Rect box;
  98.     Handle undoH;
  99.     
  100.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  101.         selStart=(**tH).selStart;
  102.         selEnd=(**tH).selEnd;
  103.         if(selStart>=selEnd) {
  104.             selStart=0;
  105.             selEnd=(**tH).teLength;
  106.         }
  107.         
  108.         undoH=FillTempHandle(tH,selStart,selEnd);
  109.         
  110.         HLock((**tH).hText);
  111.         p=*(**tH).hText+selStart;
  112.         for(i=selStart;i<selEnd;i++,p++) {
  113.             if(*p=='’' || *p=='‘') {
  114.                 *p='\'';
  115.                 dirty=1;
  116.             } else if(*p=='”' || *p=='“') {
  117.                 *p='\"';
  118.                 dirty=1;
  119.             }
  120.         }
  121.         HUnlock((**tH).hText);
  122.         if(dirty) {
  123.             if((**tH).undoBuf)
  124.                 DisposeHandle((**tH).undoBuf);
  125.             (**tH).undoBuf=undoH;
  126.             (**tH).undoStart = selStart;
  127.             (**tH).undoEnd = selEnd;
  128.             (**tH).resetUndo = false;
  129.             (**tH).undoDelta = 0;
  130.             ((DocumentPeek)wind)->fNeedtoSave=true;
  131.             SetPort(wind);
  132.             GetContentRect(wind,&box);
  133.             InvalRect(&box);
  134.             EraseRect(&box);
  135.         } else if(undoH)
  136.             DisposeHandle(undoH);
  137.     }
  138.  
  139. }
  140.  
  141. void AddLinefeeds(WindowPtr wind)
  142. {
  143.     TE32KHandle tH;
  144.     long selStart,selEnd,i,len,teBufLen;
  145.     register char *p;
  146.     Rect box;
  147.     Handle undoH,newText;
  148.     
  149.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  150.         selStart=(**tH).selStart;
  151.         selEnd=(**tH).selEnd;
  152.         len=(**tH).teLength;
  153.         if(selStart>=selEnd) {
  154.             selStart=0;
  155.             selEnd=(**tH).teLength;
  156.         }
  157.         
  158.         undoH=FillTempHandle(tH,selStart,selEnd);
  159.         teBufLen=GetHandleSize((**tH).hText);
  160.         HLock((**tH).hText);
  161.         p=*(**tH).hText+selStart;
  162.         for(i=selStart;i<selEnd;i++,p++) {
  163.             if(*p=='\n') {
  164.                 if (teBufLen < ++len) {
  165.                     HUnlock((**tH).hText);
  166.                     SetHandleSize((**tH).hText,len + 256);
  167.                     teBufLen=GetHandleSize((**tH).hText);
  168.                     if (MemError() || teBufLen < len) {
  169.                         newText=NewHandle(len + 256);
  170.                         if(!newText) {
  171.                             doMessage(1);
  172.                             return;
  173.                         }
  174.                         teBufLen=GetHandleSize((**tH).hText);
  175.                         HLock((**tH).hText);
  176.                         HLock(newText);
  177.                         
  178.                         BlockMove(*((**tH).hText),*newText,teBufLen);
  179.                         
  180.                         HUnlock((**tH).hText);
  181.                         HUnlock(newText);
  182.                         DisposeHandle((**tH).hText);
  183.                         (**tH).hText=newText;
  184.                     }
  185.                     HLock((**tH).hText);
  186.                     p=*(**tH).hText+i;
  187.                 }
  188.                 BlockMove(p+1,p+2,len-i-1);
  189.                 *(p+1)='\r';
  190.                 UpdateMarks((DocumentPeek)wind,i,i,1,(**tH).teLength);
  191.                 selEnd++;
  192.             }
  193.         }
  194.         HUnlock((**tH).hText);
  195.         if(len != (**tH).teLength) {
  196.             if((**tH).undoBuf)
  197.                 DisposeHandle((**tH).undoBuf);
  198.             (**tH).undoBuf=undoH;
  199.             (**tH).undoStart = selStart;
  200.             (**tH).selEnd=(**tH).undoEnd = selEnd;
  201.             if((**tH).selStart>selEnd);
  202.                 (**tH).selStart=selEnd;
  203.             (**tH).resetUndo = false;
  204.             (**tH).undoDelta = 0;
  205.             ((DocumentPeek)wind)->fNeedtoSave = true;
  206.             (**tH).teLength=len;
  207.             TE32KCalText(tH);
  208.             TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  209.             SetPort(wind);
  210.             GetContentRect(wind,&box);
  211.             InvalRect(&box);
  212.             EraseRect(&box);
  213.         } else if(undoH)
  214.             DisposeHandle(undoH);
  215.     }
  216. }
  217.  
  218. void StripLinefeeds(WindowPtr wind)
  219. {
  220.     TE32KHandle tH;
  221.     long selStart,selEnd,i,len;
  222.     register char *p;
  223.     Rect box;
  224.     Handle undoH;
  225.     
  226.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  227.         selStart=(**tH).selStart;
  228.         selEnd=(**tH).selEnd;
  229.         len=(**tH).teLength-1;
  230.         if(selStart>=selEnd) {
  231.             selStart=0;
  232.             selEnd=(**tH).teLength;
  233.         }
  234.         
  235.         undoH=FillTempHandle(tH,selStart,selEnd);
  236.         
  237.         HLock((**tH).hText);
  238.         p=*(**tH).hText+selStart;
  239.         for(i=selStart;i<selEnd;i++,p++) {
  240.             if(*p=='\r') {
  241.                 BlockMove(p+1,p,len-i);
  242.                 UpdateMarks((DocumentPeek)wind,i,i,-1,(**tH).teLength);
  243.                 len--;
  244.                 selEnd--;
  245.             }
  246.         }
  247.         HUnlock((**tH).hText);
  248.         if(++len != (**tH).teLength) {
  249.             if((**tH).undoBuf)
  250.                 DisposeHandle((**tH).undoBuf);
  251.             (**tH).undoBuf=undoH;
  252.             (**tH).undoStart = selStart;
  253.             (**tH).selEnd=(**tH).undoEnd = selEnd;
  254.             if((**tH).selStart>selEnd);
  255.                 (**tH).selStart=selEnd;
  256.             (**tH).resetUndo = false;
  257.             (**tH).undoDelta = 0;
  258.             ((DocumentPeek)wind)->fNeedtoSave = true;
  259.             (**tH).teLength=len;
  260.             TE32KCalText(tH);
  261.             TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  262.             SetPort(wind);
  263.             GetContentRect(wind,&box);
  264.             InvalRect(&box);
  265.             EraseRect(&box);
  266.         } else if(undoH)
  267.             DisposeHandle(undoH);
  268.     }
  269. }
  270.  
  271. void LinefeedstoReturns(WindowPtr wind)
  272. {
  273.  
  274.     TE32KHandle tH;
  275.     long selStart,selEnd,i,dirty=0;
  276.     register char *p;
  277.     Rect box;
  278.     Handle undoH;
  279.     
  280.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  281.         selStart=(**tH).selStart;
  282.         selEnd=(**tH).selEnd;
  283.         if(selStart>=selEnd) {
  284.             selStart=0;
  285.             selEnd=(**tH).teLength;
  286.         }
  287.         
  288.         undoH=FillTempHandle(tH,selStart,selEnd);
  289.         
  290.         HLock((**tH).hText);
  291.         p=*(**tH).hText+selStart;
  292.         for(i=selStart;i<selEnd;i++,p++) {
  293.             if(*p=='\r') {
  294.                 *p='\n';
  295.                 dirty=1;
  296.             } 
  297.         }
  298.         HUnlock((**tH).hText);
  299.         if(dirty) {
  300.             if((**tH).undoBuf)
  301.                 DisposeHandle((**tH).undoBuf);
  302.             (**tH).undoBuf=undoH;
  303.             (**tH).undoStart = selStart;
  304.             (**tH).undoEnd = selEnd;
  305.             (**tH).resetUndo = false;
  306.             (**tH).undoDelta = 0;
  307.             ((DocumentPeek)wind)->fNeedtoSave=true;
  308.             TE32KCalText(tH);
  309.             TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  310.             AdjustScrollBars(wind);
  311.             SetScrollBarValues(wind);
  312.             SetPort(wind);
  313.             GetContentRect(wind,&box);
  314.             InvalRect(&box);
  315.             EraseRect(&box);
  316.         } else if(undoH)
  317.             DisposeHandle(undoH);
  318.     }
  319. }
  320.  
  321. void ReturnstoLinefeeds(WindowPtr wind)
  322. {
  323.     TE32KHandle tH;
  324.     long selStart,selEnd,i,dirty=0;
  325.     register char *p;
  326.     Rect box;
  327.     Handle undoH;
  328.     
  329.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  330.         selStart=(**tH).selStart;
  331.         selEnd=(**tH).selEnd;
  332.         if(selStart>=selEnd) {
  333.             selStart=0;
  334.             selEnd=(**tH).teLength;
  335.         }
  336.         
  337.         undoH=FillTempHandle(tH,selStart,selEnd);
  338.         
  339.         HLock((**tH).hText);
  340.         p=*(**tH).hText+selStart;
  341.         for(i=selStart;i<selEnd;i++,p++) {
  342.             if(*p=='\n') {
  343.                 *p='\r';
  344.                 dirty=1;
  345.             } 
  346.         }
  347.         HUnlock((**tH).hText);
  348.         if(dirty) {
  349.             if((**tH).undoBuf)
  350.                 DisposeHandle((**tH).undoBuf);
  351.             (**tH).undoBuf=undoH;
  352.             (**tH).undoStart = selStart;
  353.             (**tH).undoEnd = selEnd;
  354.             (**tH).resetUndo = false;
  355.             (**tH).undoDelta = 0;
  356.             ((DocumentPeek)wind)->fNeedtoSave=true;
  357.             TE32KCalText(tH);
  358.             TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  359.             AdjustScrollBars(wind);
  360.             SetScrollBarValues(wind);
  361.             SetPort(wind);
  362.             GetContentRect(wind,&box);
  363.             InvalRect(&box);
  364.             EraseRect(&box);
  365.         } else if(undoH)
  366.             DisposeHandle(undoH);
  367.     }
  368. }
  369.  
  370. void FormParagraphs(WindowPtr wind)
  371. {
  372.     TE32KHandle tH;
  373.     long selStart,selEnd,i,len,dirty=0,karet;
  374.     register char *p;
  375.     Rect box;
  376.     Handle undoH;
  377.     Boolean haveSelection;
  378.     
  379.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  380.         selStart=(**tH).selStart;
  381.         selEnd=(**tH).selEnd;
  382.         if(!(haveSelection=(selStart<selEnd))) {
  383.             selStart=0;
  384.             selEnd=(**tH).teLength;
  385.             karet=(**tH).selStart;
  386.         }
  387.         
  388.         undoH=FillTempHandle(tH,selStart,selEnd);
  389.         
  390.         HLock((**tH).hText);
  391.         p=*(**tH).hText+selStart;
  392.         len=(**tH).teLength;
  393.         for(i=selStart;i<selEnd;i++,p++) {
  394.             if(*p=='\n') {
  395.                 if(*(p-1)==' ') {
  396.                     BlockMove(p,p-1,len-i);
  397.                     UpdateMarks((DocumentPeek)wind,i,i,-1,(**tH).teLength);
  398.                     if(karet>i--)
  399.                         karet--;
  400.                     len--;
  401.                     selEnd--;
  402.                     p--;
  403.                 }
  404.                 if(*(p+1)==' ' || *(p+1)=='\t' || *(p+1)=='\n' || *(p-1)=='\n' || *(p-1)=='\r')
  405.                     ;
  406.                 else {
  407.                     *p=' ';
  408.                     dirty=1;
  409.                 }
  410.             } 
  411.         }
  412.         HUnlock((**tH).hText);
  413.         if(dirty) {
  414.             if((**tH).undoBuf)
  415.                 DisposeHandle((**tH).undoBuf);
  416.             (**tH).undoBuf=undoH;
  417.             (**tH).undoStart = selStart;
  418.             (**tH).undoEnd = selEnd;
  419.             (**tH).resetUndo = false;
  420.             (**tH).undoDelta = 0;
  421.             (**tH).teLength=len;
  422.             SetTERect(wind);
  423.             TE32KCalText(tH);
  424.             if(haveSelection)
  425.                 TE32KSetSelect(selStart,selEnd,tH);
  426.             else if(karet!=(**tH).selStart)
  427.                 TE32KSetSelect(karet,karet,tH);
  428.             AdjustScrollBars(wind);
  429.             SetScrollBarValues(wind);
  430.             ((DocumentPeek)wind)->fNeedtoSave=true;
  431.             SetPort(wind);
  432.             GetContentRect(wind,&box);
  433.             InvalRect(&box);
  434.             EraseRect(&box);
  435.         } else if(undoH)
  436.             DisposeHandle(undoH);
  437.     }
  438. }
  439.  
  440. void WordWrap(WindowPtr wind, Boolean how)
  441. {
  442.     TE32KHandle tH;
  443.     long selStart,selEnd,i,len,teBufLen,nNewLines,karet,position;
  444.     register char *p;
  445.     Rect box;
  446.     Handle newText;
  447.     Boolean crOnly,wrapToLength;
  448.     Boolean haveSelection;
  449.  
  450.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  451.         selStart=(**tH).selStart;
  452.         selEnd=(**tH).selEnd;
  453.         len=(**tH).teLength;
  454.         if(!(haveSelection=(selStart<selEnd))) {
  455.             selStart=0;
  456.             selEnd=(**tH).teLength;
  457.             karet=(**tH).selStart;
  458.         }
  459.         
  460.         if((**tH).undoBuf)
  461.             DisposeHandle((**tH).undoBuf);
  462.         (**tH).undoBuf=FillTempHandle(tH,selStart,selEnd);
  463.         
  464.         wrapToLength=(**tH).wrapToLength;
  465.         crOnly=(**tH).crOnly;
  466.         
  467.         if(crOnly || (how && !wrapToLength)) {
  468.             (**tH).crOnly=0;
  469.             (**tH).wrapToLength=how;
  470.             SetTERect(wind);
  471.             TE32KCalText(tH);
  472.         }
  473.         
  474.         teBufLen=GetHandleSize((**tH).hText);
  475.         
  476.         HLock((Handle)tH);
  477.         HLock((**tH).hText);
  478.         i=1;
  479.         while(selStart>(**tH).lineStarts[i]) i++;
  480.         position=(**tH).lineStarts[i];
  481.         for(nNewLines=0;selEnd>(position=(**tH).lineStarts[i]+nNewLines);i++) {
  482.             p=*(**tH).hText+position;
  483.             if(*(p-1)!='\n') {
  484.                 if(*(p-1)==' ')
  485.                     *(p-1)='\n';
  486.                 else {
  487.                     if (teBufLen < ++len) {
  488.                         HUnlock((**tH).hText);
  489.                         HUnlock((Handle)tH);
  490.                         SetHandleSize((**tH).hText,len + 256);
  491.                         teBufLen=GetHandleSize((**tH).hText);
  492.                         if (MemError() || teBufLen < len) {
  493.                             newText=NewHandle(len + 256);
  494.                             if(!newText) {
  495.                                 doMessage(1);
  496.                                 return;
  497.                             }
  498.                             teBufLen=GetHandleSize((**tH).hText);
  499.                             HLock((**tH).hText);
  500.                             HLock(newText);
  501.                         
  502.                             BlockMove(*((**tH).hText),*newText,teBufLen);
  503.                         
  504.                             HUnlock((**tH).hText);
  505.                             HUnlock(newText);
  506.                             DisposeHandle((**tH).hText);
  507.                             (**tH).hText=newText;
  508.                         }
  509.                         HLock((Handle)tH);
  510.                         HLock((**tH).hText);
  511.                         p=*(**tH).hText+position;
  512.                     }
  513.                     BlockMove(p,p+1,len-position-1);
  514.                     UpdateMarks((DocumentPeek)wind,position,position,1,(**tH).teLength);
  515.                     if(karet>position)
  516.                         karet++;
  517.                     *(p)='\n';
  518.                     selEnd++;
  519.                     nNewLines++;
  520.                 }
  521.             }
  522.         }
  523.         
  524.         HUnlock((**tH).hText);
  525.         HUnlock((Handle)tH);
  526.         
  527.         (**tH).wrapToLength=wrapToLength;
  528.         (**tH).crOnly=crOnly;
  529.         
  530.         (**tH).undoStart = selStart;
  531.         (**tH).undoEnd = selEnd;
  532.         (**tH).resetUndo = false;
  533.         (**tH).undoDelta = 0;
  534.         ((DocumentPeek)wind)->fNeedtoSave = true;
  535.         (**tH).teLength=len;
  536.         
  537.         SetTERect(wind);
  538.         TE32KCalText(tH);
  539.         if(haveSelection)
  540.             TE32KSetSelect(selStart,selEnd,tH);
  541.         else if(karet!=(**tH).selStart)
  542.             TE32KSetSelect(karet,karet,tH);
  543.         AdjustScrollBars(wind);
  544.         SetScrollBarValues(wind);
  545.         SetPort(wind);
  546.         GetContentRect(wind,&box);
  547.         InvalRect(&box);
  548.         EraseRect(&box);
  549.     }
  550. }
  551.  
  552. void SpacesToTabs(WindowPtr wind)
  553. {
  554.     TE32KHandle tH;
  555.     long selStart,selEnd,i,len;
  556.     long tabChars;
  557.     register char *p;
  558.     Rect box;
  559.     Handle undoH;
  560.     Str255 spaces;
  561.     
  562.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  563.         tabChars=(**tH).tabChars;
  564.         selStart=(**tH).selStart;
  565.         selEnd=(**tH).selEnd;
  566.         len=(**tH).teLength;
  567.         if(selStart>=selEnd) {
  568.             selStart=0;
  569.             selEnd=(**tH).teLength;
  570.         }
  571.         
  572.         memset(spaces,' ',tabChars);
  573.         *(spaces+tabChars)=0;
  574.         
  575.         undoH=FillTempHandle(tH,selStart,selEnd);
  576.         
  577.         HLock((**tH).hText);
  578.         p=*(**tH).hText+selStart;
  579.         for(i=selStart;i<selEnd;i++,p++) {
  580.             if(*p==' ' && !strncmp(p,spaces,tabChars)) {
  581.                 BlockMove(p+tabChars,p+1,len-i-tabChars);
  582.                 *p=TAB;
  583.                 UpdateMarks((DocumentPeek)wind,i,i,-tabChars,(**tH).teLength);
  584.                 len-=(tabChars-1);
  585.                 selEnd-=(tabChars-1);
  586.             }
  587.         }
  588.         HUnlock((**tH).hText);
  589.         if(len != (**tH).teLength) {
  590.             if((**tH).undoBuf)
  591.                 DisposeHandle((**tH).undoBuf);
  592.             (**tH).undoBuf=undoH;
  593.             (**tH).undoStart = selStart;
  594.             (**tH).selEnd=(**tH).undoEnd = selEnd;
  595.             if((**tH).selStart>selEnd);
  596.                 (**tH).selStart=selEnd;
  597.             (**tH).resetUndo = false;
  598.             (**tH).undoDelta = 0;
  599.             ((DocumentPeek)wind)->fNeedtoSave = true;
  600.             (**tH).teLength=len;
  601.             TE32KCalText(tH);
  602.             TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  603.             SetPort(wind);
  604.             GetContentRect(wind,&box);
  605.             InvalRect(&box);
  606.             EraseRect(&box);
  607.         } else if(undoH)
  608.             DisposeHandle(undoH);
  609.     }
  610. }
  611.  
  612. void TabsToSpaces(WindowPtr wind)
  613. {
  614.     TE32KHandle tH;
  615.     long selStart,selEnd,i,len,teBufLen;
  616.     long tabChars,j;
  617.     register char *p;
  618.     Rect box;
  619.     Handle undoH,newText;
  620.     
  621.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  622.         selStart=(**tH).selStart;
  623.         selEnd=(**tH).selEnd;
  624.         len=(**tH).teLength;
  625.         if(selStart>=selEnd) {
  626.             selStart=0;
  627.             selEnd=(**tH).teLength;
  628.         }
  629.         
  630.         undoH=FillTempHandle(tH,selStart,selEnd);
  631.         teBufLen=GetHandleSize((**tH).hText);
  632.         tabChars=(**tH).tabChars;
  633.         
  634.         HLock((**tH).hText);
  635.         p=*(**tH).hText+selStart;
  636.         for(i=selStart;i<selEnd;i++,p++) {
  637.             if(*p==TAB) {
  638.                 if (teBufLen < (len+=(tabChars-1))) {
  639.                     HUnlock((**tH).hText);
  640.                     SetHandleSize((**tH).hText,len + 256);
  641.                     teBufLen=GetHandleSize((**tH).hText);
  642.                     if (MemError() || teBufLen < len) {
  643.                         newText=NewHandle(len + 256);
  644.                         if(!newText) {
  645.                             doMessage(1);
  646.                             return;
  647.                         }
  648.                         teBufLen=GetHandleSize((**tH).hText);
  649.                         HLock((**tH).hText);
  650.                         HLock(newText);
  651.                         
  652.                         BlockMove(*((**tH).hText),*newText,teBufLen);
  653.                         
  654.                         HUnlock((**tH).hText);
  655.                         HUnlock(newText);
  656.                         DisposeHandle((**tH).hText);
  657.                         (**tH).hText=newText;
  658.                     }
  659.                     HLock((**tH).hText);
  660.                     p=*(**tH).hText+i;
  661.                 }
  662.                 BlockMove(p+1,p+tabChars,len-i-tabChars);
  663.                 for(j=0;j<tabChars;j++) {
  664.                     *(p++)=' ';
  665.                 }
  666.                 UpdateMarks((DocumentPeek)wind,i,i,tabChars,(**tH).teLength);
  667.                 selEnd+=(tabChars-1);
  668.                 i+=(tabChars-1);
  669.             }
  670.         }
  671.         HUnlock((**tH).hText);
  672.         if(len != (**tH).teLength) {
  673.             if((**tH).undoBuf)
  674.                 DisposeHandle((**tH).undoBuf);
  675.             (**tH).undoBuf=undoH;
  676.             (**tH).undoStart = selStart;
  677.             (**tH).selEnd=(**tH).undoEnd = selEnd;
  678.             if((**tH).selStart>selEnd);
  679.                 (**tH).selStart=selEnd;
  680.             (**tH).resetUndo = false;
  681.             (**tH).undoDelta = 0;
  682.             ((DocumentPeek)wind)->fNeedtoSave = true;
  683.             (**tH).teLength=len;
  684.             TE32KCalText(tH);
  685.             TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  686.             SetPort(wind);
  687.             GetContentRect(wind,&box);
  688.             InvalRect(&box);
  689.             EraseRect(&box);
  690.         } else if(undoH)
  691.             DisposeHandle(undoH);
  692.     }
  693. }
  694.  
  695. static int VirtualEntabALine(StringPtr p,int *nTabs,int *nSpaces,int tabChars)
  696. {
  697.     int nT=0,nS=0,tabCnt;
  698.     StringPtr q;
  699.     
  700.     q=p;
  701.     while(isspace(*p)) {
  702.         if(*p==TAB) {
  703.             tabCnt=tabChars;
  704.             nS=0;
  705.             nT++;
  706.         } else if(*p==' ') {
  707.             if(!--tabCnt) {
  708.                 tabCnt=tabChars;
  709.                 nT++;
  710.                 nS=0;
  711.             } else
  712.                 nS++;
  713.         }
  714.         p++;
  715.     }
  716.     *nTabs=nT;
  717.     *nSpaces=nS;
  718.     return p-q;    /* return count to first nonspace */
  719. }
  720.  
  721. void EnTabAndShift(WindowPtr wind,int direction)
  722. {
  723.     StringPtr q;
  724.     int line,lastLine,tabChars,nMoved,position;
  725.     int selStart,selEnd,len,whiteSpace,delta,newLen;
  726.     int teBufLen;
  727.     int nAlignTabs,nAlignSpaces,nTabs,nSpaces;
  728.     TE32KHandle tH;
  729.     Handle newText;
  730.     Rect box;
  731.     
  732.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  733.         selStart=(**tH).selStart;
  734.         selEnd=(**tH).selEnd;
  735.         len=(**tH).teLength;
  736.         
  737.         if((**tH).undoBuf)
  738.             DisposeHandle((**tH).undoBuf);
  739.         (**tH).undoBuf=FillTempHandle(tH,selStart,selEnd);
  740.         
  741.         teBufLen=GetHandleSize((**tH).hText);
  742.         tabChars=(**tH).tabChars;
  743.  
  744.         HLock((Handle)tH);
  745.         HLock((**tH).hText);
  746.         
  747.         line = indexToParagraph(selStart,tH);
  748.         selStart = (**tH).lineStarts[line];
  749.  
  750.         lastLine = indexToLine(selEnd,tH);
  751.         if(selEnd > (**tH).lineStarts[lastLine])
  752.             selEnd = (**tH).lineStarts[++lastLine];
  753.         
  754.         nMoved=0;
  755.  
  756.         if(direction==0) {
  757.             position=(**tH).lineStarts[line++];
  758.             q=*(**tH).hText + position;
  759.             
  760.              whiteSpace=VirtualEntabALine(q,&nAlignTabs,&nAlignSpaces,tabChars);        
  761.         }
  762.         
  763.         for(;line<lastLine;line++) {
  764.             position=(**tH).lineStarts[line]+nMoved;
  765.             q=*(**tH).hText + position;
  766.             if((**tH).crOnly || *(q-1)==RETURN || *(q-1)==LINEFEED) {
  767.                  whiteSpace=VirtualEntabALine(q,&nTabs,&nSpaces,tabChars);        
  768.             
  769.                 if(direction==1)
  770.                     nTabs++;
  771.                 else if(direction==-1) {
  772.                     if(nTabs)
  773.                         nTabs--;
  774.                     if(!nTabs)            /* number of spaces after last tab set to zero if no tab */
  775.                         nSpaces = 0;
  776.                 } else {
  777.                     nTabs = nAlignTabs;
  778.                     nSpaces = nAlignSpaces;
  779.                 }
  780.                 
  781.                 delta = nTabs + nSpaces - whiteSpace; /* if (nTabs + nSpaces - whiteSpace) < 0 then Block move left */
  782.             
  783.                 newLen = len + delta;
  784.             
  785.                 nMoved += delta; 
  786.  
  787.                 selEnd += delta;
  788.             
  789.                 if (teBufLen < newLen) {
  790.                     HUnlock((**tH).hText);
  791.                     HUnlock((Handle)tH);
  792.                     SetHandleSize((**tH).hText,newLen + 256);
  793.                     teBufLen=GetHandleSize((**tH).hText);
  794.                     if (MemError() || teBufLen < newLen) {
  795.                         newText=NewHandle(newLen + 256);
  796.                         if(!newText) {
  797.                             doMessage(1);
  798.                             return;
  799.                         }
  800.                         teBufLen=GetHandleSize((**tH).hText);
  801.                         HLock((**tH).hText);
  802.                         HLock(newText);
  803.                     
  804.                         BlockMove(*((**tH).hText),*newText,teBufLen);
  805.                     
  806.                         HUnlock((**tH).hText);
  807.                         HUnlock(newText);
  808.                         DisposeHandle((**tH).hText);
  809.                         (**tH).hText=newText;
  810.                     }
  811.                     HLock((Handle)tH);
  812.                     HLock((**tH).hText);
  813.                     q=*(**tH).hText + position;            
  814.                 }
  815.             
  816.                 if(delta) { 
  817.                     BlockMove(q+whiteSpace,q+nTabs+nSpaces,len-position-whiteSpace);
  818.                     UpdateMarks((DocumentPeek)wind,position+nTabs+nSpaces,position+whiteSpace,delta,(**tH).teLength);
  819.                 }
  820.                             
  821.                 while(nTabs-- > 0)
  822.                     *q++ = TAB;
  823.                 while(nSpaces-- > 0)
  824.                     *q++ = ' ';
  825.             
  826.                 len = newLen;
  827.             }
  828.         }
  829.  
  830.         HUnlock((**tH).hText);
  831.         HUnlock((Handle)tH);
  832.         (**tH).undoStart = selStart;
  833.         (**tH).undoEnd = selEnd;
  834.         (**tH).resetUndo = false;
  835.         (**tH).undoDelta = 0;
  836.         ((DocumentPeek)wind)->fNeedtoSave = true;
  837.         (**tH).teLength=len;
  838.         
  839.         SetTERect(wind);
  840.         TE32KCalText(tH);
  841.         TE32KSetSelect(selStart,selEnd,tH);
  842.         AdjustScrollBars(wind);
  843.         SetScrollBarValues(wind);
  844.         SetPort(wind);
  845.         GetContentRect(wind,&box);
  846.         InvalRect(&box);
  847.         EraseRect(&box);
  848.     }
  849. }
  850.     
  851.